package org.wattdepot.gdata.kukuicup.updater.energylastthirtydays;

import it.sauronsoftware.cron4j.Scheduler;
import it.sauronsoftware.cron4j.Task;
import org.wattdepot.gdata.kukuicup.service.GDataService;
import org.wattdepot.gdata.kukuicup.service.WattDepotService;
import org.wattdepot.gdata.kukuicup.updater.Updater;

/**
 * The updater that kicks off the tasks for this spreadsheet.  
 * Given N sources to update, this updater creates N tasks that run every day 
 * after midnight and that update the last thirty days of energy consumed by that source.
 *  
 * It also creates an additional N tasks that runs every M minutes (where M is determined
 * by a property in the kukuicup.gdata.properties file) and that updates this source's energy
 * used to date for the current day only. 
 *
 * @author Philip Johnson
 */
public class EnergyLastThirtyDaysUpdater extends Updater {

  /** The property in the kukuicup.gdata.properties file indicating how often to update energy. */
  private String updateIntervalProperty = "energy.last.thirty.days.current.day.update.interval";
  /** The default interval for the current day updates if not otherwise specified. */
  private int defaultUpdateInterval = 60;
  
  /**
   * Creates this updater, initializing the various services. 
   * @param wattDepotService The wattdepot service. 
   * @param gdataService The gdata service.
   * @throws Exception If problems occur initializing these services.  
   */
  public EnergyLastThirtyDaysUpdater(WattDepotService wattDepotService, 
      GDataService gdataService) throws Exception {
    super("EnergyLastThirtyDays", wattDepotService, gdataService);
  }
  
  /**
   * This task generates two tasks for each source in the spreadsheet.
   * The first runs once a day and updates the last thirty days of data.
   * The second runs every few minutes and updates the energy used to date. 
   * All of them end up updating the spreadsheet with these values. 
   */
  @Override
  public void run() {
    // Get the update interval for getting the current day's energy consumption.
    // Defaults to once an hour if not otherwise specified.
    int updateInterval = this.wattDepotService.getProperties()
    .getIntegerProperty(updateIntervalProperty, defaultUpdateInterval);
    // Now kick off the tasks.
    scheduleColumnUpdate();
    scheduleHistoricalData();
    scheduleCurrentDayData(updateInterval);
  }
  
  /**
   * Schedules the once-a-day updates of energy consumption data for the past thirty days.
   */
  private void scheduleHistoricalData() {
    Scheduler scheduler = new Scheduler();
    schedulers.add(scheduler);
    int startMinute = 1;
    for (String sourceName : sourceNames) {
      Task task = new EnergyLastThirtyDaysHistoricalTask(wattDepotService, gdataService, 
          spreadsheetURL, sourceName, isVirtual(sourceName), getRow(sourceName));
      String schedule = startMinute + " 0 * * *";
      startMinute++;
      System.out.format("Scheduling nightly EnergyLastThirtyDays for source: %s at 12:%02d am.%n",
          sourceName, startMinute);
      scheduler.schedule(schedule, task);
      // Run the task right away to initialize the spreadsheet.
      task.execute(null);
    }
    scheduler.start();
  }
  
  /**
   * Schedules the once-a-day update of column headers.
   */
  private void scheduleColumnUpdate() {
    Scheduler scheduler = new Scheduler();
    schedulers.add(scheduler);
    Task task = new EnergyLastThirtyDaysColumnChanger(wattDepotService, gdataService, 
        spreadsheetURL);
    String schedule = "0 0 * * *";
    System.out.format("Scheduling nightly EnergyLastThirtyDays Column changer.%n");
    scheduler.schedule(schedule, task);
    // Run the task right away to initialize the spreadsheet.
    task.execute(null);
    scheduler.start();
  }

  /**
   * Schedules the every-few-minutes updates of the current day's energy consumption.
   * @param updateInterval The update interval in minutes. 
   */
  private void scheduleCurrentDayData(int updateInterval) {
    Scheduler scheduler = new Scheduler();
    schedulers.add(scheduler);
    for (String sourceName : sourceNames) {
      Task task = new EnergyLastThirtyDaysCurrentTask(wattDepotService, gdataService, 
          spreadsheetURL, sourceName, isVirtual(sourceName), getRow(sourceName));
      String schedule =  "*/" + updateInterval + " * * * *";
      System.out.format("Scheduling today's EnergyLastThirtyDays for source %s every %s minutes.%n",
          sourceName, updateInterval);
      scheduler.schedule(schedule, task);
      task.execute(null);
      //System.out.println("Pausing for 10 seconds to spread out the load on WattDepot server.");
      try {
        Thread.sleep(10000);
      }
      catch (InterruptedException e) {
        System.out.println("The sleep was interrupted. Oh well.");
      }
    }
    scheduler.start();
  }

}
